package com.brillilab.service.core.experiments.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.dao.mapper.experiments.ExperimentMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.kit.Kit;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.vo.experiments.ExperimentIconListVo;
import com.brillilab.domain.vo.topics.ExperimentDateListVo;
import com.brillilab.domain.vo.topics.TopicExperimentResultVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.experiments.IExperimentStepTimerService;
import com.brillilab.service.core.method.IMethodService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * 新实验
 *
 * @time 2019/09/05
 */
@Service
@Transactional
public class ExperimentServiceImpl implements IExperimentService {

    @Resource
    private ExperimentMapper experimentMapper;
    @Resource
    private ITopicExperimentService topicExperimentService;
    @Resource
    private ITopicService topicService;
    @Resource
    private IMethodService methodService;
    @Resource
    private IExperimentStepTimerService experimentStepTimerService;

    //****** 老逻辑 可用 *******/
    @Override
    public Experiment getUnderWayOrNotStarted(Long experimentTargetId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getTopicExperimentId, experimentTargetId);
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.in(Experiment::getState, ExperimentStateEnum.NOT_STARTED.getValue(), ExperimentStateEnum.UNDER_WAY.getValue());
        return experimentMapper.selectOne(wrapper);
    }

    public Experiment selectExperimentByStepId(Long stepId) {
        Assert.isTrue(stepId != null, "参数缺失！");
        return experimentMapper.selectExperimentByStepId(stepId);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Experiment> getListByDescEndTime(Long experimentTargetId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getTopicExperimentId, experimentTargetId);
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.orderByDesc(Experiment::getEndTime);
        return experimentMapper.selectList(wrapper);
    }

    @Override
    public List<Experiment> selectByIdsAndNotEnd(List<Long> experimentIds) {
        if (experimentIds != null && experimentIds.size() > 0) {
            LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Experiment::getId, experimentIds);
            wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
            wrapper.in(Experiment::getState, ExperimentStateEnum.NOT_STARTED.getValue(), ExperimentStateEnum.UNDER_WAY.getValue());
            return experimentMapper.selectList(wrapper);
        }
        return new ArrayList<>(0);
    }
    //***** end *****//

    @Override
    public Experiment selectById(Long experimentId) {
        Assert.isTrue(experimentId != null, "请求参数缺失!");
        return experimentMapper.selectById(experimentId);
    }

    @Override

    public List<Experiment> getListByTopicId(List<Long> topicIds) {
        if (CollectionUtils.isNotEmpty(topicIds)) {
            return experimentMapper.getListByTopicIds(topicIds);
        }
        return new ArrayList<Experiment>();
    }

    @Override
    public List<Experiment> getPlanExperimentListByLabId(Long labId,List<Long> executorIds) {
        return  experimentMapper.getPlanExperimentListByLabId(labId,executorIds);
    }

    @Override
    public List<Experiment> getExperimentByConditionList(Long labMemberId, List<Integer> stateList) {
        LambdaQueryWrapper<Experiment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Experiment::getExecutorId, labMemberId);
        if(CollectionUtils.isNotEmpty(stateList)) {
            queryWrapper.in(Experiment::getState, stateList);
        }
        queryWrapper.eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue());
        return experimentMapper.selectList(queryWrapper);
    }

    @Override
    public List<Experiment> getExperimentList(Long labMemberId, Date beginDate, Date endDate) {
        LambdaQueryWrapper<Experiment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Experiment::getExecutorId, labMemberId);
        queryWrapper.ge(Experiment::getCreateTime, beginDate);
        queryWrapper.le(Experiment::getCreateTime, endDate);
        queryWrapper.eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue());
        return experimentMapper.selectList(queryWrapper);
    }

    @Override
    public List<Experiment> getExperimentByStateList(Long labMemberId, Integer state) {
        LambdaQueryWrapper<Experiment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Experiment::getExecutorId, labMemberId);
        queryWrapper.eq(Experiment::getState, state);
        queryWrapper.eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue());
        return experimentMapper.selectList(queryWrapper);
    }

    public List<Experiment> selectByIds(List<Long> experimentIds) {
        if(CollectionUtils.isNotEmpty(experimentIds)){
            LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Experiment::getId, experimentIds);
            wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
            wrapper.orderByDesc(Experiment::getId);
            return experimentMapper.selectList(wrapper);
        }
        return new ArrayList<Experiment>();
    }

    @Override
    public boolean updateById(Experiment experiment) {
        return experimentMapper.updateById(experiment) > 0;
    }

    @Override
    public int getCountByTargetId(Long targetId, List<Integer> states) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.eq(Experiment::getTopicTargetId, targetId);
        wrapper.in(Experiment::getState, states);
        return experimentMapper.selectCount(wrapper);
    }

    @Override
    public List<TopicExperimentResultVo> getExperimentHistory(Long topicExperimentId) {
        return experimentMapper.getExperimentHistory(topicExperimentId);
    }

    @Override
    public int getCountByTopicExperimentId(Long topicExperimentId, List<Integer> states) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.eq(Experiment::getTopicExperimentId, topicExperimentId);
        wrapper.in(Experiment::getState, states);
        return experimentMapper.selectCount(wrapper);
    }

    @Override
    public List<ExperimentDateListVo> getExperimentDateListVo(List<Long> topicExperimentIds, Long targetGroupId) {
        return experimentMapper.getExperimentDateListVo(topicExperimentIds, targetGroupId);
    }

    @Override
    public List<ExperimentIconListVo> getExperimentIconVoList(List<Long> experimentIds) {
        return experimentMapper.getExperimentIconVoList(experimentIds);
    }


    @Override
    public List<Kit> experimentKitList(Long experimentId) {
        return experimentMapper.selectExperimentKitList(experimentId);
    }

    @Override
    public Experiment experimentAdd(TopicExperiment topicExperiment) {

        Experiment experiment = new Experiment();
        experiment.setLabId(topicExperiment.getLabId());
        experiment.setTopicId(topicExperiment.getTopicId());
        experiment.setTopicDirectionId(topicExperiment.getTopicDirectionId());
        experiment.setTopicTargetId(topicExperiment.getTopicTargetId());
        experiment.setTopicExperimentId(topicExperiment.getId());
        experiment.setSerial(topicExperiment.getSerial());
        experiment.setExecutorId(topicExperiment.getExecutorId());
        experiment.setIsCheck(topicExperiment.getIsCheck());
        experiment.setFirstTypeId(topicExperiment.getFirstTypeId());
        experiment.setMethodTypeId(topicExperiment.getMethodTypeId());
        experiment.setMethodId(topicExperiment.getMethodId());
        experiment.setName(topicExperiment.getMethodTypeName());
        int insert = experimentMapper.insert(experiment);
        Assert.isTrue(insert == 1, "创建实验失败");

        topicExperiment.setExperimentId(experiment.getId());
        topicExperimentService.updateById(topicExperiment);
        return experiment;
    }

    @Override
    public void updateByNewMethod(Long executorId) {
        Experiment experiment = new Experiment();
        experiment.setId(executorId);
        experiment.setIsNewMethod(BoolEnum.TRUE.getValue());
        this.updateById(experiment);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Experiment> getExperimentList(Long topicTargetId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.eq(Experiment::getTopicTargetId, topicTargetId);
        wrapper.orderByDesc(Experiment::getSerial);
        return experimentMapper.selectList(wrapper);
    }

    @Override
    public void endExperiment(Long experimentId, Integer isExpect) {
        //结束实验
        Experiment experiment = experimentMapper.selectById(experimentId);
        Assert.notNull(experiment, "实验不存在!");
        experiment.setState(ExperimentStateEnum.COMPLETE.getValue());
        if (experiment.getStartTime() == null) {
            experiment.setStartTime(new Date());
        }
        experiment.setEndTime(new Date());
        if (isExpect != null)
            experiment.setIsExpect(isExpect);
        experimentMapper.updateById(experiment);

        //结束所有实验计时器
        experimentStepTimerService.endTimersByExperimentId(experimentId);

    }

    @Override
    public List<Experiment> getExperimentList(Long topicExperimentId, Integer state) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.eq(Experiment::getTopicExperimentId, topicExperimentId);
        if (state != null) {
            wrapper.eq(Experiment::getState, state);
        }
        return experimentMapper.selectList(wrapper);
    }

    @Override
    public List<Long> selectIdByTopicIds(List<Long> topicIds) {
        if (topicIds != null && topicIds.size() > 0) {
            return experimentMapper.selectIdByTopicIds(topicIds);
        }
        return null;
    }


    @Override
    public int getExperimentCount(Long labId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getLabId, labId);
        wrapper.eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue());
        return experimentMapper.selectCount(wrapper);
    }

    @Override
    public int getExperimentCountByExecutorId(Long executorId) {
        return experimentMapper.getExperimentCountByExecutorId(executorId);
    }

    @Override
    public List<Experiment> selectLastExperiment(Long experimentId) {
        List<Experiment> experimentList = experimentMapper.selectLastExperiment(experimentId);
        return experimentList;
    }

    @Override
    public Experiment insert(Experiment experiment) {
        experimentMapper.insert(experiment);
        return experiment;
    }

    @Override
    public List<Experiment> getPublishList(Long topicExperimentId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Experiment::getTopicExperimentId, topicExperimentId);
        wrapper.eq(Experiment::getIsDelete, IsDeleteEnum.NO.getValue());
        wrapper.eq(Experiment::getIsPublish, BoolEnum.TRUE.getValue());
        return experimentMapper.selectList(wrapper);
    }

    @Override
    public void evaluationSetting(Long experimentId, Integer result, Integer publish) {
        Experiment experiment = new Experiment();
        experiment.setId(experimentId);
        experiment.setIsExpect(result);
        experiment.setIsPublish(publish);
        experimentMapper.updateById(experiment);
    }

    @Override
    public void experimentGuideSetting(Long experimentId, Integer type, Integer operate) {
        Experiment experiment = new Experiment();
        experiment.setId(experimentId);
        if (type == 1) {
            experiment.setIsAddGroup(operate);
        } else if (type == 2) {
            experiment.setIsAddAnalyze(operate);
        } else if (type == 3) {
            experiment.setIsAddTrouble(operate);
        }
        experimentMapper.updateById(experiment);
    }

    @Override
    public void deleteByIds(List<Long> experimentIds) {
        experimentMapper.deleteBatchIds(experimentIds);
    }

    @Override
    public void deleteById(Long experimentId) {
        experimentMapper.deleteById(experimentId);
    }

    @Override
    public List<Experiment> selectIdByTopicIds(Long topicId) {
        return experimentMapper.selectList(
                new LambdaQueryWrapper<Experiment>()
                        .eq(Experiment::getTopicId, topicId)
                        .eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue()));
    }

    @Override
    public List<Experiment> selectByTopicTargetId(Long topicTargetId) {
        return experimentMapper.selectList(
                new LambdaQueryWrapper<Experiment>()
                        .eq(Experiment::getTopicTargetId, topicTargetId)
                        .eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue()));
    }

    @Override
    @SuppressWarnings("unchecked")
    public Experiment getLatestExperiment(Long topicExperimentId) {
        LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<Experiment>();
        wrapper.eq(Experiment::getTopicExperimentId, topicExperimentId);
        wrapper.eq(Experiment::getIsDelete, BoolEnum.FALSE.getValue());
        wrapper.orderByDesc(Experiment::getId);
        List<Experiment> list = experimentMapper.selectList(wrapper);
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    @Override
    public void delete(Long topicDirectionId, Long topicTargetId, Long topicExperimentId) {
        if (topicDirectionId != null || topicTargetId != null || topicExperimentId != null) {
            LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<Experiment>();
            if (topicDirectionId != null)
                wrapper.eq(Experiment::getTopicDirectionId, topicDirectionId);
            if (topicTargetId != null)
                wrapper.eq(Experiment::getTopicTargetId, topicTargetId);
            if (topicExperimentId != null)
                wrapper.eq(Experiment::getTopicExperimentId, topicExperimentId);
            Experiment entity = new Experiment();
            entity.setIsDelete(BoolEnum.TRUE.getValue());
            experimentMapper.update(entity, wrapper);
        }
    }

	@Override
	public void endExperimentByTopicId(Long topicId) {
		LambdaQueryWrapper<Experiment> wrapper = new LambdaQueryWrapper<Experiment>();
		wrapper.eq(Experiment::getTopicId, topicId);
		wrapper.ne(Experiment::getState, ExperimentStateEnum.COMPLETE.getValue());
		Experiment entity = new Experiment();
		entity.setState(ExperimentStateEnum.COMPLETE.getValue());
		experimentMapper.update(entity, wrapper);
	}

    @Override
    public List<Experiment> getGuideExperimentList(Long labId, List<Long> labMemberIdList) {
        return experimentMapper.getGuideExperimentList(labId, labMemberIdList);
    }


}
